package com.hf.mail

import java.util.concurrent.atomic.AtomicReference

import javax.mail.internet.MimeMessage

import org.springframework.mail.javamail.JavaMailSender
import org.springframework.mail.javamail.JavaMailSenderImpl
import org.springframework.mail.javamail.MimeMessageHelper
import org.springframework.scheduling.concurrent.ConcurrentTaskExecutor

import com.hf.constant.OrderLunchConst

class MailSenderService {
	//	public static final String SMTP_CONNECTION_TIMEOUT_MS = "20000";
	//	public static final String SMTP_SOCKET_TIMEOUT_MS = "10000";

	def grailsApplication
	def config

	static transactional = false

	ConcurrentTaskExecutor concurrentTaskExecutor

	private AtomicReference mailSender  = new AtomicReference();

	public void send(MailMessage mailMessage) {
		log.info "Sending to: ${mailMessage.to}"
		MimeMessage message = this.getJavaMailSender().createMimeMessage()

		MimeMessageHelper helper = new MimeMessageHelper(message,true,"UTF-8")

		mailMessage.to.each { helper.addTo(it) }

		if(mailMessage.from) {
			helper.setFrom(mailMessage.from, mailMessage.fromPersonal)
		} else {
			helper.setFrom(OrderLunchConst.ADMIN_EMAIL, OrderLunchConst.ADMIN_NAME)
		}

		if(mailMessage.replyTo){
			helper.setReplyTo(mailMessage.replyTo, mailMessage.replyToPersonal)
		}

		mailMessage.Cc.each{ helper.addCc(it) }

		mailMessage.Bcc.each{ helper.addBcc(it) }

		helper.setSubject(mailMessage.subject)

		if(mailMessage.plainText){
			helper.setText(mailMessage.plainText, false)
		}
		if(mailMessage.htmlText){
			helper.setText(mailMessage.htmlText, true)
		}

		helper.setSentDate(mailMessage.sendDate ?: new Date())

		this.getJavaMailSender().send(helper.getMimeMessage());
		log.info "Sent to: ${mailMessage.to}"
	}

	public void sendAsyn(MailMessage mailMessage) {
		send(mailMessage)
//		concurrentTaskExecutor.execute(new Runnable() {
//			public void run() {
//				try {
//					log.info mailMessage.to
//					send(mailMessage)
//				} catch (Exception exception) {
//					log.error("Fail to send mail asyn, ${mailMessage}", exception)
//				}
//			}
//		})
	}

	private JavaMailSender getJavaMailSender() {
		JavaMailSender sender = this.mailSender.get()
		if (null == sender) {
			sender = refreshJavaMailSender()
		}
		return sender
	}

	private synchronized JavaMailSender refreshJavaMailSender() {
		JavaMailSender sender = this.mailSender.get()
		if (null == sender) {
			sender = this.createJavaMailSender()
			this.mailSender.set(sender)
		}
		return sender
	}

	private JavaMailSender createJavaMailSender() {
		config = grailsApplication.config

		Properties connectionProperties = new Properties();

		JavaMailSenderImpl newMailSender = new JavaMailSenderImpl();

		newMailSender.setProtocol(config.mail.protocol);

		newMailSender.setPort(Integer.parseInt(config.mail.port));

		newMailSender.setHost(config.mail.host);

		return newMailSender;
	}

}
